package com.gt.quality.apim.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gt.quality.apim.domain.APIForHttpUtils;
import com.gt.quality.apim.domain.ApiDataInfo;
import com.gt.quality.apim.domain.ApiParamInfo;
import com.gt.quality.apim.domain.ApiRelationshipInterfaceInfo;
import com.gt.quality.apim.domain.vo.APIInterfaceVo;
import com.gt.quality.apim.domain.vo.ApiDataInfoVo;
import com.gt.quality.apim.service.ApiDataInfoService;
import com.gt.quality.apim.service.ApiParamInfoService;
import com.gt.quality.base.BusinessSelfException;
import com.gt.quality.config.SpringBeanUtil;
import com.gt.quality.config.utils.LoginHelper;
import com.gt.quality.config.utils.LoginUser;
import com.gt.quality.system.mapper.ApiDataInfoMapper;
import com.gt.quality.system.service.modelservice.MybatisPlusModelServiceProxy;
import com.gt.quality.base.pojo.BaseLimitRequest;
import com.gt.quality.base.pojo.Resp;
import com.gt.quality.system.service.GTBaseService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionTemplate;

import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * API数据集表(ApiDataInfo)表服务实现类
 *
 * @author makejava
 * @since 2026-11-20 09:37:49
 */
@Service("apiDataInfoService")
@Slf4j
public class ApiDataInfoServiceImpl extends ServiceImpl<ApiDataInfoMapper, ApiDataInfo> implements GTBaseService<ApiDataInfo>, ApiDataInfoService {


    private ApiDataInfoMapper apiDataInfoMapper;


    private ApiParamInfoService apiParamInfoService;

    /**
     * Model代理器--获取SQL执行Model->ApiRelationshipInterfaceInfo
     */
    private MybatisPlusModelServiceProxy mybatisPlusModelServiceProxy;

    /**
     * Model代理器
     */
    @Autowired
    public void setMybatisPlusModelServiceProxy(MybatisPlusModelServiceProxy mybatisPlusModelServiceProxy) {
        this.mybatisPlusModelServiceProxy = mybatisPlusModelServiceProxy;
    }


    @Autowired
    public void setApiDataInfoMapper(ApiDataInfoMapper apiDataInfoMapper) {
        this.apiDataInfoMapper = apiDataInfoMapper;
    }


    @Autowired
    public void setApiParamInfoService(ApiParamInfoService apiParamInfoService) {
        this.apiParamInfoService = apiParamInfoService;
    }

    /**
     * 往上传递 SqlSessionFactory
     *
     * @return SqlSessionFactory
     */
    @Override
    public SqlSessionFactory getSqlSessionFactory() {
        return super.getSqlSessionFactory();
    }

    /**
     * 往上传递 Mapper
     *
     * @return Mapper
     */
    @Override
    public Class<?> getThisMapperClass() {
        return ApiDataInfoMapper.class;
    }

    /**
     * 往上传递 Transaction
     *
     * @return Transaction
     */
    @Override
    public TransactionTemplate getSpringTx() {
        return SpringBeanUtil.getBean(TransactionTemplate.class);
    }

    /**
     * Description:  分页查询
     *
     * @param limitRequest 分页查询参数
     * @author: makeJava
     * @date: com.sjhy.plugin.tool.TimeUtils@65a47fee
     * @return:com.baomidou.mybatisplus.core.metadata.IPage
     */
    @Override
    public IPage<ApiDataInfo> queryLimitPage(BaseLimitRequest<ApiDataInfo> limitRequest) {
        ApiDataInfo requestBody = limitRequest.getRequestBody();
        IPage<ApiDataInfo> page = getByPageParam(limitRequest);
        if (requestBody == null) {
            return apiDataInfoMapper.selectPage(page, new QueryWrapper<>());
        }
        LambdaQueryWrapper<ApiDataInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(StringUtils.isNotBlank(requestBody.getApiName()), ApiDataInfo::getApiName, requestBody.getApiName());
        queryWrapper.orderByDesc(ApiDataInfo::getCreateTime);
        return apiDataInfoMapper.selectPage(page, queryWrapper);
    }

    /**
     * Description:  批量新增优化版
     *
     * @param entityList entityList
     * @author: makeJava
     * @date: com.sjhy.plugin.tool.TimeUtils@65a47fee
     */
    @Override
    public Integer saveBatchByEasyBaseMapper(List<ApiDataInfo> entityList) {

        return apiDataInfoMapper.insertBatch(entityList);
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveApiInfoAndParam(ApiDataInfoVo apiDataInfo) {
        try {
            JSONObject entries = JSONUtil.parseObj(apiDataInfo);
            ApiDataInfo bean = JSONUtil.toBean(entries, ApiDataInfo.class);
            LoginUser loginUser = Objects.requireNonNull(LoginHelper.getLoginUser());

            // 设置基础信息
            bean.setCreateBy(loginUser.getUserId());
            bean.setDeleteFlag(0);
            bean.setUpdateBy(loginUser.getUserId());
            bean.setUpdateTime(new Date());
            bean.setApiCode(IdUtil.fastSimpleUUID());
            bean.setCreateDept(loginUser.getDeptId());

            // 插入主表数据
            int insertResult = apiDataInfoMapper.insert(bean);
            if (insertResult <= 0) {
                log.error("API数据插入失败");
                return false;
            }

            // 更新主键ID
            apiDataInfo.setId(bean.getId());

            // 处理参数列表
            List<ApiParamInfo> apiParamInfoList = apiDataInfo.getApiParamInfoList();
            if (CollUtil.isEmpty(apiParamInfoList)) {
                return true;
            }

            for (ApiParamInfo apiParamInfo : apiParamInfoList) {
                // 根据参数类型设置默认值
                if (apiParamInfo.getParamDefineType() == 100) {
                    apiParamInfo.setParamDefaultValue(null);
                }
                // 设置基础信息
                apiParamInfo.setCreateBy(loginUser.getUsername());
                apiParamInfo.setDeleteFlag(0);
                apiParamInfo.setUpdateBy(loginUser.getUsername());
                apiParamInfo.setUpdateTime(new Date());
                apiParamInfo.setApiInfoId(bean.getId());
                apiParamInfo.setCreateDept(loginUser.getDeptName());

                // 处理接口信息
                if (apiParamInfo.getInterfaceInfo() != null && "API".equals(apiParamInfo.getParamCategory())) {
                    ApiRelationshipInterfaceInfo interfaceInfo = apiParamInfo.getInterfaceInfo();
                    interfaceInfo.setCreateBy(bean.getCreateBy());
                    interfaceInfo.setUpdateBy(bean.getUpdateBy());
                    interfaceInfo.setCreateDept(bean.getCreateDept());
                    boolean insertInterfaceResult = interfaceInfo.insert();
                    if (!insertInterfaceResult) {
                        log.error("接口信息插入失败");
                        return false;
                    }
                    apiParamInfo.setApiRelationshipInterfaceId(interfaceInfo.getId().toString());
                }

                // 保存参数信息
                if (!apiParamInfoService.save(apiParamInfo)) {
                    log.error("参数信息保存失败");
                    return false;
                }
            }

            return true;
        } catch (Exception e) {
            log.error("保存API信息和参数失败", e);
            throw new BusinessSelfException("保存API信息和参数失败：" + e.getMessage());
        }
    }


    @Override
    public Resp<Object> executeApi(ApiDataInfoVo apiDataInfo) {
        String apiUrl = apiDataInfo.getApiUrl();
        String apiReqMethod = apiDataInfo.getApiReqMethod();
        String apiContentType = apiDataInfo.getApiContentType();
        List<ApiParamInfo> apiParamInfoList = apiDataInfo.getApiParamInfoList();
        return toAjaxResult(apiUrl, apiContentType, apiParamInfoList, apiReqMethod);
    }

    @Override
    public ApiDataInfoVo getByIdAndSon(Serializable id) {
        ApiDataInfoVo dataInfoVo = apiDataInfoMapper.queryById(id);
        List<ApiParamInfo> apiParamInfoList = dataInfoVo.getApiParamInfoList();
        if (CollUtil.isNotEmpty(apiParamInfoList)) {
            ApiRelationshipInterfaceInfo info = mybatisPlusModelServiceProxy.getApiRelationshipInterfaceInfo();
            for (ApiParamInfo apiParamInfo : apiParamInfoList) {
                if (StringUtils.isNotBlank(apiParamInfo.getApiRelationshipInterfaceId())) {
                    ApiRelationshipInterfaceInfo interfaceInfo = info.selectById(Long.valueOf(apiParamInfo.getApiRelationshipInterfaceId()));
                    apiParamInfo.setInterfaceInfo(interfaceInfo);
                }
            }
        }
        return dataInfoVo;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean removeByIdsAndSon(List<Long> idList) {
        int mainTables = apiDataInfoMapper.deleteByIds(idList);
        if (mainTables > 0) {
            // 移除子表
            UpdateWrapper<ApiParamInfo> updateWrapper = new UpdateWrapper<>();
            updateWrapper.in("api_info_id", idList);
            apiParamInfoService.remove(updateWrapper);
        }
        return true;
    }


    @Override
    public Resp<Object> executeApiByListApiParam(List<ApiParamInfo> apiParamInfoList) {
        Long apiInfoId = apiParamInfoList.get(0).getApiInfoId();
        ApiDataInfo apiDataInfo = this.getById(apiInfoId);
        return toAjaxResult(apiDataInfo.getApiUrl(), apiDataInfo.getApiContentType(), apiParamInfoList, apiDataInfo.getApiReqMethod());
    }

    @Transactional
    @Override
    public void beforeDeleteParamListAndNewInsert(Long id, List<ApiParamInfo> apiParamInfoList) {
        LoginUser loginUser = Objects.requireNonNull(LoginHelper.getLoginUser());
        QueryWrapper<ApiParamInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("api_info_id", id);
        List<ApiParamInfo> list = apiParamInfoService.list(queryWrapper);
        if (CollUtil.isNotEmpty(list)) {
            // 移除关联关系
            Set<String> stringSet = list.stream().map(ApiParamInfo::getApiRelationshipInterfaceId).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
            if (CollUtil.isNotEmpty(stringSet)) {
                ApiRelationshipInterfaceInfo info = mybatisPlusModelServiceProxy.getApiRelationshipInterfaceInfo();
                for (String idStr : stringSet) {
                    info.deleteById(Long.valueOf(idStr));
                }
            }
            // 移除小主表
            apiParamInfoService.removeBatchByIds(list.stream().map(ApiParamInfo::getId).toList());
        }
        if (CollUtil.isNotEmpty(apiParamInfoList)) {
            for (ApiParamInfo apiParamInfo : apiParamInfoList) {
                apiParamInfo.setId(null);
                apiParamInfo.setApiInfoId(id);
                apiParamInfo.setCreateBy(loginUser.getUsername());
                apiParamInfo.setDeleteFlag(0);
                apiParamInfo.setUpdateBy(loginUser.getUsername());
                apiParamInfo.setUpdateTime(new Date());
                apiParamInfo.setCreateDept(loginUser.getDeptName());
                if (apiParamInfo.getInterfaceInfo() != null) {
                    ApiRelationshipInterfaceInfo interfaceInfo = apiParamInfo.getInterfaceInfo();
                    interfaceInfo.setId(null);
                    interfaceInfo.setCreateDept(loginUser.getDeptId());
                    interfaceInfo.setCreateBy(loginUser.getUserId());
                    interfaceInfo.setUpdateBy(loginUser.getUserId());
                    interfaceInfo.insert();
                    apiParamInfo.setApiRelationshipInterfaceId(interfaceInfo.getId().toString());
                }
            }
            apiParamInfoService.saveBatch(apiParamInfoList);
        }
    }

    private Resp<Object> toAjaxResult(String apiUrl, String contentType, List<ApiParamInfo> apiParamInfoList, String apiReqMethod) {
        Map<String, String> httpClientConfig = new HashMap<>();
        StringBuilder apiUrlBuilder = new StringBuilder(apiUrl);
        StringBuilder apiParams = new StringBuilder("?");
        JSONObject body = new JSONObject();

        buildRequestComponents(apiUrlBuilder, apiParams, body, httpClientConfig, apiParamInfoList);

        Resp<Object> result = executeHttpRequest(apiUrlBuilder.toString(), apiParams.toString(), httpClientConfig, body, contentType, apiReqMethod);

        if (result.getCode() != Resp.SUCCESS) {
            log.error("HTTP请求失败: {}", result.getMsg());
            return Resp.error("HTTP请求失败：" + result.getMsg());
        }

        return result;
    }

    private void buildRequestComponents(StringBuilder apiUrlBuilder, StringBuilder apiParams, JSONObject body, Map<String, String> httpClientConfig, List<ApiParamInfo> apiParamInfoList) {
        for (ApiParamInfo apiParamInfo : apiParamInfoList) {
            String paramPosition = apiParamInfo.getParamPosition();
            switch (paramPosition) {
                case APIForHttpUtils.PARAM_POSITION_BODY:
                    buildBody(body, apiParamInfo);
                    break;
                case APIForHttpUtils.PARAM_POSITION_HEADER:
                    buildHeader(httpClientConfig, apiParamInfo);
                    break;
                case APIForHttpUtils.PARAM_POSITION_QUERY:
                    buildQuery(apiParams, apiParamInfo);
                    break;
                case APIForHttpUtils.PARAM_POSITION_PATH:
                    buildPath(apiUrlBuilder, apiParamInfo);
                    break;
                default:
                    log.error("未知参数放置位置");
            }
        }
    }

    private void buildBody(JSONObject body, ApiParamInfo apiParamInfo) {
        switch (apiParamInfo.getParamCategory()) {
            case APIForHttpUtils.PARAM_TYPE_JSON:
                body.set(apiParamInfo.getParamName(), StringUtils.isBlank(apiParamInfo.getParamDefaultValue()) ? new JSONObject() : JSONUtil.parseObj(apiParamInfo.getParamDefaultValue()));
                break;
            case APIForHttpUtils.PARAM_TYPE_ARRAY:
                body.set(apiParamInfo.getParamName(), apiParamInfo.getParamDefaultValue().split(","));
                break;
            case APIForHttpUtils.PARAM_TYPE_API:
                body.set(apiParamInfo.getParamName(), buildNextApiGetValue(apiParamInfo));
                break;
            default:
                body.set(apiParamInfo.getParamName(), apiParamInfo.getParamDefaultValue());
        }
    }

    private void buildHeader(Map<String, String> httpClientConfig, ApiParamInfo apiParamInfo) {
        httpClientConfig.put(apiParamInfo.getParamName(), apiParamInfo.getParamDefaultValue());
        if (apiParamInfo.getParamCategory().equals(APIForHttpUtils.PARAM_TYPE_API)) {
            Object byPathValue = buildNextApiGetValue(apiParamInfo);
            httpClientConfig.put(apiParamInfo.getParamName(), byPathValue.toString());
        }
    }

    private void buildQuery(StringBuilder apiParams, ApiParamInfo apiParamInfo) {
        if (apiParamInfo.getParamCategory().equals(APIForHttpUtils.PARAM_TYPE_ARRAY)) {
            String[] split = apiParamInfo.getParamDefaultValue().split(",");
            for (String item : split) {
                apiParams.append(apiParamInfo.getParamName()).append("=").append(item).append("&");
            }
        } else if (apiParamInfo.getParamCategory().equals(APIForHttpUtils.PARAM_TYPE_API)) {
            Object byPathValue = buildNextApiGetValue(apiParamInfo);
            apiParams.append(apiParamInfo.getParamName()).append("=").append(byPathValue).append("&");
        } else {
            apiParams.append(apiParamInfo.getParamName()).append("=").append(apiParamInfo.getParamDefaultValue()).append("&");
        }
    }

    private void buildPath(StringBuilder apiUrlBuilder, ApiParamInfo apiParamInfo) {
        if (apiParamInfo.getParamCategory().equals(APIForHttpUtils.PARAM_TYPE_API)) {
            Object byPathValue = buildNextApiGetValue(apiParamInfo);
            apiUrlBuilder.append("/").append(byPathValue);
        } else {
            apiUrlBuilder.append("/").append(apiParamInfo.getParamDefaultValue());
        }
    }

    private Resp<Object> executeHttpRequest(String apiUrl, String apiParams, Map<String, String> httpClientConfig, JSONObject body, String contentType, String apiReqMethod) {
        Resp<Object> result = Resp.error("不支持的请求类型.{" + apiReqMethod + "}");
        String finalUrl = apiUrl + apiParams;

        try {
            switch (apiReqMethod) {
                case APIForHttpUtils.METHOD_GET:
                    try (HttpResponse response = HttpRequest.get(finalUrl).addHeaders(httpClientConfig).timeout(30000).execute()) {
                        result = createSuccessResponse(response.body(), finalUrl, httpClientConfig, body);
                    }
                    break;
                case APIForHttpUtils.METHOD_POST:
                    if (contentType.contains("form")) {
                        try (HttpResponse response = HttpRequest.post(finalUrl).form(body).addHeaders(httpClientConfig).timeout(30000).execute()) {
                            result = createSuccessResponse(response.body(), finalUrl, httpClientConfig, body);
                        }
                    } else {
                        try (HttpResponse response = HttpRequest.post(finalUrl).body(JSONUtil.toJsonStr(body)).addHeaders(httpClientConfig).timeout(30000).execute()) {
                            result = createSuccessResponse(response.body(), finalUrl, httpClientConfig, body);
                        }
                    }
                    break;
                case APIForHttpUtils.METHOD_PUT:
                    try (HttpResponse response = HttpRequest.put(finalUrl).body(JSONUtil.toJsonStr(body)).addHeaders(httpClientConfig).timeout(30000).execute()) {
                        result = createSuccessResponse(response.body(), finalUrl, httpClientConfig, body);
                    }
                    break;
                case APIForHttpUtils.METHOD_DELETE:
                    try (HttpResponse response = HttpRequest.delete(finalUrl).body(JSONUtil.toJsonStr(body)).addHeaders(httpClientConfig).timeout(30000).execute()) {
                        result = createSuccessResponse(response.body(), finalUrl, httpClientConfig, body);
                    }
                    break;
                default:
                    return result;
            }
        } catch (Exception e) {
            log.error("HTTP请求失败", e);
            return Resp.error("HTTP请求失败：" + e.getMessage());
        }
        return result;
    }

    private Resp<Object> createSuccessResponse(String remoteResult, String finalUrl, Map<String, String> httpClientConfig, JSONObject body) {
        Resp<Object> result = new Resp<>();
        result.setCode(Resp.SUCCESS);
        JSONObject reqMsg = new JSONObject();
        reqMsg.set("URL", finalUrl);
        reqMsg.set("Header", httpClientConfig);
        reqMsg.set("Body", body);
        result.setMsg(reqMsg.toString());
        result.setData(remoteResult);
        return result;
    }
    /**
     * 构建API参数的值
     *
     * @param apiParamInfo apiParamInfo
     */
    private Object buildNextApiGetValue(ApiParamInfo apiParamInfo) {
        // 二步接口请求获取参数值
        ApiRelationshipInterfaceInfo interfaceInfo = apiParamInfo.getInterfaceInfo();
        if (interfaceInfo == null) {
            ApiRelationshipInterfaceInfo queryBoss = mybatisPlusModelServiceProxy.getApiRelationshipInterfaceInfo();
            interfaceInfo = queryBoss.selectById(apiParamInfo.getApiRelationshipInterfaceId());
        }
        Long apiId = interfaceInfo.getApiId();
        // 获取本次API的关联记录值
        String paramDefaultValue = interfaceInfo.getParamDefaultValue();
        List<APIInterfaceVo> entriesList = JSONUtil.toList(paramDefaultValue, APIInterfaceVo.class);
        ApiDataInfoVo nextRequest = this.getByIdAndSon(apiId);
        List<ApiParamInfo> apiParamInfoList = nextRequest.getApiParamInfoList();
        // 替换值---发起API请求
        if (CollUtil.isNotEmpty(apiParamInfoList)) {
            for (ApiParamInfo paramInfo : apiParamInfoList) {
                // 遍历拆组包
                for (APIInterfaceVo jsonObject : entriesList) {
                    if (paramInfo.getParamName().equals(jsonObject.getParamName())) {
                        paramInfo.setParamDefaultValue(jsonObject.getParamDefaultValue());
                        break;
                    }
                }
            }
        }
        Resp<Object> ajax = toAjaxResult(nextRequest.getApiUrl(), nextRequest.getApiContentType(), apiParamInfoList, nextRequest.getApiReqMethod());
        if (Resp.isSuccess(ajax)) {
            Object data = ajax.getData();
            JSONObject entries1 = JSONUtil.parseObj(data);
            return entries1.getByPath(StringUtils.isNotBlank(apiParamInfo.getParamDefaultValue()) ? apiParamInfo.getParamDefaultValue() : interfaceInfo.getParamJsonPath());
        } else {
            throw new BusinessSelfException(ajax.getMsg());
        }
    }

}


